package com.zhou.app.favourite.security.athentication;

import com.zhou.app.favourite.cache.LoginFailRetryNumGuavaCache;
import com.zhou.app.favourite.service.impl.SysUserServiceImpl;
import com.zhou.app.favourite.util.ServletUtil;
import com.zhou.common.lib.model.Response;
import com.zhou.common.lib.util.JSONUtils;
import com.zhou.common.operator.log.core.constant.OperateActionEnum;
import com.zhou.common.operator.log.core.model.OperateLogInfo;
import com.zhou.common.operator.log.core.model.PrincipalInfo;
import com.zhou.common.operator.log.core.resolver.ClientInfoResolver;
import com.zhou.common.operator.log.core.service.OperateLogStorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * Security 认证失败 Handler
 * <p>
 * @serial 2.0.0
 * @author 就眠儀式
 */
@Slf4j
@Component
public class SecureAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Resource
    private ClientInfoResolver clientInfoResolver;

    @Autowired
    private SysUserServiceImpl sysUserService;

    @Resource
    private OperateLogStorageService logService;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        log.info("登录失败");
        Response result = Response.error(500, "登录失败");

//        if (e instanceof CaptchaException) {
//            result.setMsg("验证码有误");
//        }
        if (e instanceof UsernameNotFoundException) {
            result.setMsg("用户名不存在");
            LoginFailRetryNumGuavaCache.addCount(request.getParameter("username"));
        }
        if ((e instanceof InternalAuthenticationServiceException && e.getCause() instanceof LockedException)
                || (e instanceof LockedException)) {
            result.setMsg("用户冻结");
        }
        if (e instanceof BadCredentialsException) {
            result.setMsg("账户密码不正确");
            LoginFailRetryNumGuavaCache.addCount(request.getParameter("username"));
        }
        if (e instanceof DisabledException) {
            result.setMsg("用户未启用");
            LoginFailRetryNumGuavaCache.addCount(request.getParameter("username"));
        }
        OperateLogInfo logInfo = new OperateLogInfo();
        logInfo.setClientInfo(this.clientInfoResolver.resolveClientInfo(request));
        logInfo.setAddTime(new Date());
        PrincipalInfo principalInfo = new PrincipalInfo();
        principalInfo.setUserName(request.getParameter("username"));
        logInfo.setPrincipal(principalInfo);
        logInfo.setOperatingInstruction("登录失败:" + result.getMsg());
        logInfo.setAction(OperateActionEnum.LOGIN.getAction());
        this.logService.append(logInfo);

        ServletUtil.write(JSONUtils.toJson(result));
    }
}
